﻿/*****************************************************
**Copyright(C), 2021-2022, Ciqtek Technology.
**Version:     1.0
**Author:      dingyy
**Date:        2021/08/30
**Description: 基础对话框
*****************************************************/

#ifndef WINDOWIMPLBASE_H
#define WINDOWIMPLBASE_H

#include "../generalui_global.h"
#include "../GlobalUIDef.h"

#include <QDialog>
#include <QMargins>

namespace GeneralUI {

	class GENERALUI_EXPORT WindowImplBase : public QDialog
	{
		Q_OBJECT

	public:
		/** 窗口显示状态（为了兼容边框阴影，需要定制最大化/最大化恢复，代码需要自己管理显示状态）
		 */
		enum WindowShowState
		{
			SHOW_NORMAL,        ///< 正常显示
			SHOW_MINIMIZED,     ///< 最小化显示
			SHOW_MAXIMIZED,     ///< 最大化显示
		};

		/**
		 * @brief  窗口操作类型
		 */
		enum OperateType
		{
			OP_NONE,        ///< 无操作
			OP_MOVE,        ///< 移动
			OP_RESIZE       ///< 调整大小
		};

		/**
		 * @brief  调整大小方向
		 */
		enum ResizeDirection
		{
			NONE,               ///< 无调整
			TOP,                ///< 顶部
			BOTTOM,             ///< 底部
			LEFT,               ///< 左边
			RIGHT,              ///< 右边
			TOP_LEFT,           ///< 左上
			TOP_RIGHT,          ///< 右上
			BOTTOM_LEFT,        ///< 左下
			BOTTOM_RIGHT        ///< 右下
		};

	public:
		/**
		 * @brief  WindowImplBase 构造函数
		 * @param  parent
		 * @return
		 */
		WindowImplBase(QWidget *parent);

		/**
		 * @brief  ~WindowImplBase 析构函数
		 * @return
		 */
		~WindowImplBase();

	public:
		/**
		 * @brief  setEnableWindowMinMax 设置窗口是否启用最大化最小化（改变大小），默认禁用（需要等窗口所有子控件创建之后调用）
		 * @param  bEnable
		 * @return void
		 */
		void setEnableWindowMinMax(bool bEnable = false);

		/**
		 * @brief  setWindowShadowMargins 设置窗口阴影边框大小
		 * @param  shadowMargin
		 * @return void
		 */
		void setWindowShadowMargins(const QMargins& shadowMargin);

		/**
		 * @brief  setJudgeResizeDistacne 设置鼠标移动时，是否可以resize的判断距离（指鼠标距离窗口边界/顶点的距离）
		 * @param  nDistacne
		 * @return void
		 */
		void setJudgeResizeDistacne(const int nDistacne);

		/**
		 * @brief  showNormal 正常显示
		 * @return void
		 */
		void showNormal();

		/**
		 * @brief  showMaximized 最大化显示
		 * @return void
		 */
		void showMaximized();

		/**
		 * @brief  showMinimized 最小化显示
		 * @return void
		 */
		void showMinimized();

		/**
		 * @brief  isMaximized 判断是否最大化
		 * @return bool
		 */
		bool isMaximized() const;

		/**
		 * @brief  isMinimized 判断是否最小化
		 * @return bool
		 */
		bool isMinimized() const;

	Q_SIGNALS:
		/**
		 * @brief  signalWindowStateChanged 窗口状态变化时(最大化/最小化/恢复正常大小)发送信号
		 * @param  eState 	WindowShowState枚举类型
		 * @return void
		 */
		void signalWindowStateChanged(WindowShowState eState);

	protected:
		/**
		 * @brief  paintEvent 绘制事件
		 * @param  event
		 * @return void
		 */
		void paintEvent(QPaintEvent *event) override;

		/**
		 * @brief  eventFilter 事件处理
		 * @param  obj
		 * @param  event
		 * @return bool
		 */
		bool eventFilter(QObject *obj, QEvent *event) override;

		/**
		 * @brief  setVisible 显示/隐藏窗口
		 * @param  visible
		 * @return void
		 */
		void setVisible(bool visible) override;

		/**
		 * @brief  mouseMoveEvent 鼠标移动事件
		 * @param  event
		 * @return void
		 */
		void mouseMoveEvent(QMouseEvent *event) override;

		/**
		 * @brief  mousePressEvent 鼠标按下事件
		 * @param  event
		 * @return void
		 */
		void mousePressEvent(QMouseEvent *event) override;

		/**
		 * @brief  mouseReleaseEvent 鼠标释放事件
		 * @param  event
		 * @return void
		 */
		void mouseReleaseEvent(QMouseEvent *event) override;

		/**
		 * @brief  mouseDoubleClickEvent 鼠标双击事件
		 * @param  event
		 * @return void
		 */
		void mouseDoubleClickEvent(QMouseEvent *event) override;

	private:
		/**
		 * @brief  adjustRect  调整窗口大小位置
		 * @param  rect
		 * @return void
		 */
		void adjustRect(const QRect& rect);

		/**
		 * @brief  judgeRelationshipPointAndRegions 判断鼠标位置与窗口区域的关系
		 * @param  point
		 * @return void
		 */
		void judgeRelationshipPointAndRegions(const QPoint& point);

		/**
		 * @brief  distanceFromTwoPoint 判断两点间距
		 * @param  p1
		 * @param  p2
		 * @return double
		 */
		double distanceFromTwoPoint(QPointF p1, QPointF p2);

		/**
		 * @brief  resizeWindowByMouseMove 根据鼠标移动位置调整窗口大小
		 * @param  mousePos
		 * @return void
		 */
		void resizeWindowByMouseMove(const QPoint& mousePos);

		/**
		 * @brief  recoverSizeWhenMaximizedMove 当最大化时拖拽，恢复原先大小
		 * @param  mousePos
		 * @return void
		 */
		void recoverSizeWhenMaximizedMove(const QPoint& mousePos);

		/**
		 * @brief  stopOperate  结束操作
		 * @return void
		 */
		void stopOperate();

	private:
		/** 是否支持最大化最小化（是否支持Resize）
		 */
		bool m_bEnableMinMax;

		/** 窗口阴影边界
		 */
		QMargins m_shadowMargin;

		/** 判断可以Resize的距离
		 */
		int m_nJudgeResizeDistance;

		/** 窗口显示状态
		 */
		WindowShowState m_eShowState;

		/** 最小化之前的状态，最小化还原时需要
		 */
		WindowShowState m_eMinimizedRecoverState;

		/** 正常显示的窗口大小，恢复显示时需要
		 */
		QRect m_normalShowRect;

		/** 操作类型
		 */
		OperateType m_eOpType;

		/** 调整大小方向
		 */
		ResizeDirection m_eDirection;

		/** 鼠标按下位置，窗口拖拽或调整大小时需要
		 */
		QPoint m_pressPoint;
	};

}//namespace OfUI

#endif // WINDOWIMPLBASE_H

